from myelin.Ns import MYELIN_RULES
from myelin.lib import DateTime
from myelin.server.core.ft import ModelDriver

from nodetypes.models.rules.PublishingRule import PublishingRule as ModelClass

from AclBaseRule import AclBaseRule


class PublishingRule(AclBaseRule):
    
    modelClass = ModelClass
    
    newDbDriver = staticmethod(ModelDriver.FromRepo)
    currentDateTimeAsStr = staticmethod(DateTime.CurrentAsString)
    
    def execute(self, context, model):  
        
        # convert rule to a PublishRule
        model = model.rdf_castTo(self.modelClass)
        
        if __debug__:
            print "Publishing Rule for: %s" % model.rdf_value
        
        # get current dateTime
        cur_dt = self.currentDateTimeAsStr()
        
        # keep track of 'rule-for' nodes (ruleNodes) processed
        c = 0
        
        # extract server
        server = context.server
        
        dbDriver = model.Initialize(
            self.newDbDriver(
                context.repo,
                getattr(server.defaults,'data_model_name',None)
            )
        )
        
        # extract server
        cacheInv = server.cacheMgr.getInvalidator(context.repo)
                
        ruleNodes = model.rRule_For
        for node in ruleNodes:
            print "Attempting to process rule for node: %s" % node.rdf_value
            print "Current time is: %s" % cur_dt
            node.rdf_reset(dbDriver)
            
            for dt in node.mEffectiveDate:
                if cur_dt < dt.rdf_value:
                    continue
                
                print "Trying to publish node with effective date: %s" % dt.rdf_value
                
                error = False
                for parent in node.mParentUnpublished:
                    if node.rdf_add('mParentPublished', parent.rdf_value):
                        parent.rdf_remove()
                        for rtype in parent.rdfType:
                            cacheInv.invalidateKey(
                                rtype.rdf_scope
                            )
                    else:
                        print "Problem occurred while trying to publish node: %s" % node.rdf_value
                        error = True
                        
                # check acl updates
                self.applyAcls(context, model, node.rdf_scope)                    
                
                # setting resetState=True is important!
                # because below rActive is being removed on the same model
                node.rdf_flush(True)
                
                # invalidate cache for node
                for rtype in node.rdfType:
                    cacheInv.invalidateKey(
                        rtype.rdf_scope
                    )
                
                # successfully processed rule for this node, so increment
                if not error:
                    c += 1
                
                print "Successfully published node."
                break
                    
        # If we processed rule for all associated nodes
        # then this rule is done and can be inactivated
        if len(ruleNodes) == c:
            print "Successfully completed processing of rule; will inactive rule"
            for node in model.rActive:
                node.rdf_remove()
            model.rdf_flush()


RULE_TYPES = {
    MYELIN_RULES + 'PublishingRule' : PublishingRule,
}

# cleanup
del DateTime
del AclBaseRule
del ModelDriver
del MYELIN_RULES
del ModelClass